/*
 * Arena.cpp
 *
 *  Created on: Nov 11, 2010
 *      Author: dhovemey
 */

#include <cassert>
#include "runtime/Object.h"
#include "runtime/Class.h"
#include "runtime/VirtualMachine.h"
#include "runtime/Arena.h"

ArenaIterator::ArenaIterator(VirtualMachine *vm, Arena *arena)
	: m_vm(vm)
	, m_arena(arena)
	, m_ptr(arena->m_buf)
{

}

ArenaIterator::~ArenaIterator()
{
}

bool ArenaIterator::hasNext() const
{
	return m_ptr < m_arena->m_next;
}

Object *ArenaIterator::next()
{
	assert(hasNext());

	Object *obj = reinterpret_cast<Object*>(m_ptr);

	// based on current object's size, figure out where next object will be
	Class *cls = m_vm->getClassForClassId(obj->clsId);
	m_ptr += cls->getObjectSize();

	return obj;
}

Arena::Arena(VirtualMachine *vm, size_t size)
	: m_vm(vm)
	, m_buf(new char[size])
	, m_size(size)
	, m_next(m_buf)
{

}

Arena::~Arena()
{

}

Object *Arena::alloc(Class *cls)
{
	size_t used = (m_next - m_buf);
	size_t remaining = m_size - used;
	size_t needed = cls->getObjectSize();

	if (needed > remaining) {
		return 0;
	}

	Object *obj = reinterpret_cast<Object*>(m_next);
	m_next += needed;
	cls->initialize(obj);
	return obj;
}

ArenaIterator *Arena::iterator()
{
	return new ArenaIterator(m_vm, this);
}
